{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f0100cdc",
   "metadata": {
    "papermill": {
     "duration": 0.051507,
     "end_time": "2022-03-20T03:21:48.747089",
     "exception": false,
     "start_time": "2022-03-20T03:21:48.695582",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "# Overview\n",
    "**Tutorial**: recbole-using-all-items-for-prediction\n",
    "\n",
    "**Author**: [astrung](https://github.com/astrung)\n",
    "\n",
    "**Original link**: [notebook](https://www.kaggle.com/code/astrung/recbole-using-all-items-for-prediction/notebook)\n",
    "\n",
    "**Edit**: \n",
    "I have create new notebooks for applying our customize function for using all items as input for recommendation:\n",
    "* Using only interactions: https://www.kaggle.com/astrung/sequential-model-fixed-missing-last-item\n",
    "* Using interactions with item features: https://www.kaggle.com/code/astrung/lstm-model-with-item-infor-fix-missing-last-item\n",
    "\n",
    "- - -\n",
    "\n",
    "In my previous [notebook](https://www.kaggle.com/code/astrung/recbole-lstm-sequential-for-recomendation-tutorial) about sequential model with Recbole, someone asked me about the mechanism of test data when using `full_sort_topk` for prediction submitted recommendation in this [comment](https://www.kaggle.com/code/astrung/recbole-lstm-sequential-for-recomendation-tutorial/comments#1723707) and this [comment](https://www.kaggle.com/code/astrung/recbole-lstm-sequential-for-recomendation-tutorial/comments#1723707), and they have a doubt about whether we are using all items for getting final recommendation. Most of people has 2 questions about using `full_sort_topk` with test data:\n",
    "1. Do items in test data are used as input features for getting recommendation ?\n",
    "2. If test data is necessary for getting recommendation in Recbole API, how can we get recommendation without splitting into train/test data?\n",
    "\n",
    "In this notebook i will answer all questions:\n",
    "1. Yes. In sequential models, items in test data is used as input features, but not last items. As a example, if user X have 3 items in test data(A, B, C) and 5 items in train data(a,b,c,d,e), test data will generate 3 sample rows for evaluating performance on user X:\n",
    "* Row 1: Input features: `a,b,c,d,e,0,0`. Output features: `A`. `0` is a pad item\n",
    "* Row 2: Input features: `a,b,c,d,e,A,0`. Output features: `B`.\n",
    "* Row 3: Input features: `a,b,c,d,e,A,B`. Output features: `C`.\n",
    "\n",
    "In my previous notebook, i use last row result as recommendation, **so we still using nearly all of items as input for recommendation, except last item(item C)**. Our recommendation in previous notebooks may be not perfect, but it is simple as a tutorial for anyone want to start.\n",
    "\n",
    "**Note: This mechanism is only for sequential model in recbole. For other types of model, it isn't correct - it won't use items in test data for getting recommendation. If you have requests for explaining for other model, please upvote and comment. I will explain it in other notebook**\n",
    "\n",
    "In first session of this notebook, i will dig into test data to prove this conclusion.\n",
    "\n",
    "2. Yes, we can get recommendation by using all of items as input features, without splitting train/test. In order to do this, you need to modify recbole code:\n",
    "* Fist, you copy last row in dataset(input features have all items, except last one), then add last item into input features.\n",
    "* Then you predict directly from model api, without using [full_sort_score or full_sort_topk](https://recbole.io/docs/user_guide/usage/case_study.html)\n",
    "\n",
    "In second session of this notebook, i will show you how to do that.\n",
    "\n",
    "Ok, let start"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bbb84f80",
   "metadata": {
    "papermill": {
     "duration": 0.092534,
     "end_time": "2022-03-20T03:21:48.923117",
     "exception": false,
     "start_time": "2022-03-20T03:21:48.830583",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "# I. How test items are used in test data.\n",
    "\n",
    "For each item in test data, it will be generated as a sample row. As a example, if user X have 3 items in test data(A, B, C) and 5 items in train data(a,b,c,d,e), test data will generate 3 sample rows for evaluating performance on user X:\n",
    "* Row 1: Input features: `a,b,c,d,e,0,0`. Output label: `A`. `0` is a pad item\n",
    "* Row 2: Input features: `a,b,c,d,e,A,0`. Output label: `B`.\n",
    "* Row 3: Input features: `a,b,c,d,e,A,B`. Output label: `C`.\n",
    "\n",
    "For proving it, we will create a dataset, then extract input features and label in test data.\n",
    "\n",
    "### 1. Let create test data in recbole"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "796894e4",
   "metadata": {
    "_cell_guid": "b1076dfc-b9ad-4769-8c92-a6c4dae69d19",
    "_uuid": "8f2839f25d086af736a60e9eeb907d3b93b6e0e5",
    "execution": {
     "iopub.execute_input": "2022-03-20T03:21:49.077123Z",
     "iopub.status.busy": "2022-03-20T03:21:49.076011Z",
     "iopub.status.idle": "2022-03-20T03:22:10.110393Z",
     "shell.execute_reply": "2022-03-20T03:22:10.109242Z",
     "shell.execute_reply.started": "2022-03-19T07:15:02.071127Z"
    },
    "papermill": {
     "duration": 21.115617,
     "end_time": "2022-03-20T03:22:10.110594",
     "exception": false,
     "start_time": "2022-03-20T03:21:48.994977",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting recbole\r\n",
      "  Downloading recbole-1.0.1-py3-none-any.whl (2.0 MB)\r\n",
      "     |████████████████████████████████| 2.0 MB 537 kB/s            \r\n",
      "\u001b[?25hRequirement already satisfied: pandas>=1.0.5 in /opt/conda/lib/python3.7/site-packages (from recbole) (1.3.5)\r\n",
      "Collecting colorlog==4.7.2\r\n",
      "  Downloading colorlog-4.7.2-py2.py3-none-any.whl (10 kB)\r\n",
      "Collecting scipy==1.6.0\r\n",
      "  Downloading scipy-1.6.0-cp37-cp37m-manylinux1_x86_64.whl (27.4 MB)\r\n",
      "     |████████████████████████████████| 27.4 MB 99 kB/s              \r\n",
      "\u001b[?25hRequirement already satisfied: torch>=1.7.0 in /opt/conda/lib/python3.7/site-packages (from recbole) (1.9.1)\r\n",
      "Requirement already satisfied: colorama==0.4.4 in /opt/conda/lib/python3.7/site-packages (from recbole) (0.4.4)\r\n",
      "Requirement already satisfied: numpy>=1.17.2 in /opt/conda/lib/python3.7/site-packages (from recbole) (1.20.3)\r\n",
      "Requirement already satisfied: pyyaml>=5.1.0 in /opt/conda/lib/python3.7/site-packages (from recbole) (6.0)\r\n",
      "Requirement already satisfied: tensorboard>=2.5.0 in /opt/conda/lib/python3.7/site-packages (from recbole) (2.6.0)\r\n",
      "Requirement already satisfied: scikit-learn>=0.23.2 in /opt/conda/lib/python3.7/site-packages (from recbole) (1.0.1)\r\n",
      "Requirement already satisfied: tqdm>=4.48.2 in /opt/conda/lib/python3.7/site-packages (from recbole) (4.62.3)\r\n",
      "Requirement already satisfied: python-dateutil>=2.7.3 in /opt/conda/lib/python3.7/site-packages (from pandas>=1.0.5->recbole) (2.8.2)\r\n",
      "Requirement already satisfied: pytz>=2017.3 in /opt/conda/lib/python3.7/site-packages (from pandas>=1.0.5->recbole) (2021.3)\r\n",
      "Requirement already satisfied: threadpoolctl>=2.0.0 in /opt/conda/lib/python3.7/site-packages (from scikit-learn>=0.23.2->recbole) (3.0.0)\r\n",
      "Requirement already satisfied: joblib>=0.11 in /opt/conda/lib/python3.7/site-packages (from scikit-learn>=0.23.2->recbole) (1.1.0)\r\n",
      "Requirement already satisfied: tensorboard-plugin-wit>=1.6.0 in /opt/conda/lib/python3.7/site-packages (from tensorboard>=2.5.0->recbole) (1.8.0)\r\n",
      "Requirement already satisfied: setuptools>=41.0.0 in /opt/conda/lib/python3.7/site-packages (from tensorboard>=2.5.0->recbole) (59.5.0)\r\n",
      "Requirement already satisfied: google-auth-oauthlib<0.5,>=0.4.1 in /opt/conda/lib/python3.7/site-packages (from tensorboard>=2.5.0->recbole) (0.4.6)\r\n",
      "Requirement already satisfied: requests<3,>=2.21.0 in /opt/conda/lib/python3.7/site-packages (from tensorboard>=2.5.0->recbole) (2.26.0)\r\n",
      "Requirement already satisfied: werkzeug>=0.11.15 in /opt/conda/lib/python3.7/site-packages (from tensorboard>=2.5.0->recbole) (2.0.2)\r\n",
      "Requirement already satisfied: absl-py>=0.4 in /opt/conda/lib/python3.7/site-packages (from tensorboard>=2.5.0->recbole) (0.15.0)\r\n",
      "Requirement already satisfied: tensorboard-data-server<0.7.0,>=0.6.0 in /opt/conda/lib/python3.7/site-packages (from tensorboard>=2.5.0->recbole) (0.6.1)\r\n",
      "Requirement already satisfied: wheel>=0.26 in /opt/conda/lib/python3.7/site-packages (from tensorboard>=2.5.0->recbole) (0.37.0)\r\n",
      "Requirement already satisfied: protobuf>=3.6.0 in /opt/conda/lib/python3.7/site-packages (from tensorboard>=2.5.0->recbole) (3.19.4)\r\n",
      "Requirement already satisfied: google-auth<2,>=1.6.3 in /opt/conda/lib/python3.7/site-packages (from tensorboard>=2.5.0->recbole) (1.35.0)\r\n",
      "Requirement already satisfied: grpcio>=1.24.3 in /opt/conda/lib/python3.7/site-packages (from tensorboard>=2.5.0->recbole) (1.43.0)\r\n",
      "Requirement already satisfied: markdown>=2.6.8 in /opt/conda/lib/python3.7/site-packages (from tensorboard>=2.5.0->recbole) (3.3.6)\r\n",
      "Requirement already satisfied: typing-extensions in /opt/conda/lib/python3.7/site-packages (from torch>=1.7.0->recbole) (4.1.1)\r\n",
      "Requirement already satisfied: six in /opt/conda/lib/python3.7/site-packages (from absl-py>=0.4->tensorboard>=2.5.0->recbole) (1.16.0)\r\n",
      "Requirement already satisfied: cachetools<5.0,>=2.0.0 in /opt/conda/lib/python3.7/site-packages (from google-auth<2,>=1.6.3->tensorboard>=2.5.0->recbole) (4.2.4)\r\n",
      "Requirement already satisfied: pyasn1-modules>=0.2.1 in /opt/conda/lib/python3.7/site-packages (from google-auth<2,>=1.6.3->tensorboard>=2.5.0->recbole) (0.2.7)\r\n",
      "Requirement already satisfied: rsa<5,>=3.1.4 in /opt/conda/lib/python3.7/site-packages (from google-auth<2,>=1.6.3->tensorboard>=2.5.0->recbole) (4.8)\r\n",
      "Requirement already satisfied: requests-oauthlib>=0.7.0 in /opt/conda/lib/python3.7/site-packages (from google-auth-oauthlib<0.5,>=0.4.1->tensorboard>=2.5.0->recbole) (1.3.0)\r\n",
      "Requirement already satisfied: importlib-metadata>=4.4 in /opt/conda/lib/python3.7/site-packages (from markdown>=2.6.8->tensorboard>=2.5.0->recbole) (4.11.3)\r\n",
      "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /opt/conda/lib/python3.7/site-packages (from requests<3,>=2.21.0->tensorboard>=2.5.0->recbole) (1.26.7)\r\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /opt/conda/lib/python3.7/site-packages (from requests<3,>=2.21.0->tensorboard>=2.5.0->recbole) (2021.10.8)\r\n",
      "Requirement already satisfied: charset-normalizer~=2.0.0 in /opt/conda/lib/python3.7/site-packages (from requests<3,>=2.21.0->tensorboard>=2.5.0->recbole) (2.0.9)\r\n",
      "Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.7/site-packages (from requests<3,>=2.21.0->tensorboard>=2.5.0->recbole) (3.1)\r\n",
      "Requirement already satisfied: zipp>=0.5 in /opt/conda/lib/python3.7/site-packages (from importlib-metadata>=4.4->markdown>=2.6.8->tensorboard>=2.5.0->recbole) (3.6.0)\r\n",
      "Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /opt/conda/lib/python3.7/site-packages (from pyasn1-modules>=0.2.1->google-auth<2,>=1.6.3->tensorboard>=2.5.0->recbole) (0.4.8)\r\n",
      "Requirement already satisfied: oauthlib>=3.0.0 in /opt/conda/lib/python3.7/site-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<0.5,>=0.4.1->tensorboard>=2.5.0->recbole) (3.1.1)\r\n",
      "Installing collected packages: scipy, colorlog, recbole\r\n",
      "  Attempting uninstall: scipy\r\n",
      "    Found existing installation: scipy 1.7.3\r\n",
      "    Uninstalling scipy-1.7.3:\r\n",
      "      Successfully uninstalled scipy-1.7.3\r\n",
      "  Attempting uninstall: colorlog\r\n",
      "    Found existing installation: colorlog 6.6.0\r\n",
      "    Uninstalling colorlog-6.6.0:\r\n",
      "      Successfully uninstalled colorlog-6.6.0\r\n",
      "\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\r\n",
      "pymc3 3.11.5 requires scipy<1.8.0,>=1.7.3, but you have scipy 1.6.0 which is incompatible.\r\n",
      "pdpbox 0.2.1 requires matplotlib==3.1.1, but you have matplotlib 3.5.1 which is incompatible.\r\n",
      "featuretools 1.6.0 requires numpy>=1.21.0, but you have numpy 1.20.3 which is incompatible.\r\n",
      "arviz 0.11.4 requires typing-extensions<4,>=3.7.4.3, but you have typing-extensions 4.1.1 which is incompatible.\u001b[0m\r\n",
      "Successfully installed colorlog-4.7.2 recbole-1.0.1 scipy-1.6.0\r\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\r\n"
     ]
    }
   ],
   "source": [
    "!pip install recbole"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "73239bab",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:22:10.257515Z",
     "iopub.status.busy": "2022-03-20T03:22:10.256377Z",
     "iopub.status.idle": "2022-03-20T03:23:16.176085Z",
     "shell.execute_reply": "2022-03-20T03:23:16.176596Z",
     "shell.execute_reply.started": "2022-03-19T07:15:17.429911Z"
    },
    "papermill": {
     "duration": 65.997767,
     "end_time": "2022-03-20T03:23:16.176777",
     "exception": false,
     "start_time": "2022-03-20T03:22:10.179010",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>t_dat</th>\n",
       "      <th>customer_id</th>\n",
       "      <th>article_id</th>\n",
       "      <th>price</th>\n",
       "      <th>sales_channel_id</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2018-09-20</td>\n",
       "      <td>000058a12d5b43e67d225668fa1f8d618c13dc232df0ca...</td>\n",
       "      <td>0663713001</td>\n",
       "      <td>0.050831</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2018-09-20</td>\n",
       "      <td>000058a12d5b43e67d225668fa1f8d618c13dc232df0ca...</td>\n",
       "      <td>0541518023</td>\n",
       "      <td>0.030492</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2018-09-20</td>\n",
       "      <td>00007d2de826758b65a93dd24ce629ed66842531df6699...</td>\n",
       "      <td>0505221004</td>\n",
       "      <td>0.015237</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2018-09-20</td>\n",
       "      <td>00007d2de826758b65a93dd24ce629ed66842531df6699...</td>\n",
       "      <td>0685687003</td>\n",
       "      <td>0.016932</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2018-09-20</td>\n",
       "      <td>00007d2de826758b65a93dd24ce629ed66842531df6699...</td>\n",
       "      <td>0685687004</td>\n",
       "      <td>0.016932</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        t_dat                                        customer_id  article_id  \\\n",
       "0  2018-09-20  000058a12d5b43e67d225668fa1f8d618c13dc232df0ca...  0663713001   \n",
       "1  2018-09-20  000058a12d5b43e67d225668fa1f8d618c13dc232df0ca...  0541518023   \n",
       "2  2018-09-20  00007d2de826758b65a93dd24ce629ed66842531df6699...  0505221004   \n",
       "3  2018-09-20  00007d2de826758b65a93dd24ce629ed66842531df6699...  0685687003   \n",
       "4  2018-09-20  00007d2de826758b65a93dd24ce629ed66842531df6699...  0685687004   \n",
       "\n",
       "      price  sales_channel_id  \n",
       "0  0.050831                 2  \n",
       "1  0.030492                 2  \n",
       "2  0.015237                 2  \n",
       "3  0.016932                 2  \n",
       "4  0.016932                 2  "
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "df = pd.read_csv(r\"/kaggle/input/h-and-m-personalized-fashion-recommendations/transactions_train.csv\", \n",
    "                 dtype={'article_id': 'str'})\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "26fe44ff",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:23:18.242810Z",
     "iopub.status.busy": "2022-03-20T03:23:18.241761Z",
     "iopub.status.idle": "2022-03-20T03:23:23.253894Z",
     "shell.execute_reply": "2022-03-20T03:23:23.254595Z",
     "shell.execute_reply.started": "2022-03-19T07:16:16.934597Z"
    },
    "papermill": {
     "duration": 7.012762,
     "end_time": "2022-03-20T03:23:23.254783",
     "exception": false,
     "start_time": "2022-03-20T03:23:16.242021",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>t_dat</th>\n",
       "      <th>customer_id</th>\n",
       "      <th>article_id</th>\n",
       "      <th>price</th>\n",
       "      <th>sales_channel_id</th>\n",
       "      <th>timestamp</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2018-09-20</td>\n",
       "      <td>000058a12d5b43e67d225668fa1f8d618c13dc232df0ca...</td>\n",
       "      <td>0663713001</td>\n",
       "      <td>0.050831</td>\n",
       "      <td>2</td>\n",
       "      <td>1537401600</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2018-09-20</td>\n",
       "      <td>000058a12d5b43e67d225668fa1f8d618c13dc232df0ca...</td>\n",
       "      <td>0541518023</td>\n",
       "      <td>0.030492</td>\n",
       "      <td>2</td>\n",
       "      <td>1537401600</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2018-09-20</td>\n",
       "      <td>00007d2de826758b65a93dd24ce629ed66842531df6699...</td>\n",
       "      <td>0505221004</td>\n",
       "      <td>0.015237</td>\n",
       "      <td>2</td>\n",
       "      <td>1537401600</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2018-09-20</td>\n",
       "      <td>00007d2de826758b65a93dd24ce629ed66842531df6699...</td>\n",
       "      <td>0685687003</td>\n",
       "      <td>0.016932</td>\n",
       "      <td>2</td>\n",
       "      <td>1537401600</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2018-09-20</td>\n",
       "      <td>00007d2de826758b65a93dd24ce629ed66842531df6699...</td>\n",
       "      <td>0685687004</td>\n",
       "      <td>0.016932</td>\n",
       "      <td>2</td>\n",
       "      <td>1537401600</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       t_dat                                        customer_id  article_id  \\\n",
       "0 2018-09-20  000058a12d5b43e67d225668fa1f8d618c13dc232df0ca...  0663713001   \n",
       "1 2018-09-20  000058a12d5b43e67d225668fa1f8d618c13dc232df0ca...  0541518023   \n",
       "2 2018-09-20  00007d2de826758b65a93dd24ce629ed66842531df6699...  0505221004   \n",
       "3 2018-09-20  00007d2de826758b65a93dd24ce629ed66842531df6699...  0685687003   \n",
       "4 2018-09-20  00007d2de826758b65a93dd24ce629ed66842531df6699...  0685687004   \n",
       "\n",
       "      price  sales_channel_id   timestamp  \n",
       "0  0.050831                 2  1537401600  \n",
       "1  0.030492                 2  1537401600  \n",
       "2  0.015237                 2  1537401600  \n",
       "3  0.016932                 2  1537401600  \n",
       "4  0.016932                 2  1537401600  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "df['t_dat'] = pd.to_datetime(df['t_dat'], format=\"%Y-%m-%d\")\n",
    "df['timestamp'] = df.t_dat.values.astype(np.int64) // 10 ** 9\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "b4b9ffc7",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:23:23.406061Z",
     "iopub.status.busy": "2022-03-20T03:23:23.404925Z",
     "iopub.status.idle": "2022-03-20T03:23:25.058648Z",
     "shell.execute_reply": "2022-03-20T03:23:25.059139Z",
     "shell.execute_reply.started": "2022-03-19T07:16:23.242276Z"
    },
    "papermill": {
     "duration": 1.734735,
     "end_time": "2022-03-20T03:23:25.059306",
     "exception": false,
     "start_time": "2022-03-20T03:23:23.324571",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user_id:token</th>\n",
       "      <th>item_id:token</th>\n",
       "      <th>timestamp:float</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>23934157</th>\n",
       "      <td>000058a12d5b43e67d225668fa1f8d618c13dc232df0ca...</td>\n",
       "      <td>0727808001</td>\n",
       "      <td>1585699200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23934158</th>\n",
       "      <td>000058a12d5b43e67d225668fa1f8d618c13dc232df0ca...</td>\n",
       "      <td>0727808007</td>\n",
       "      <td>1585699200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23934159</th>\n",
       "      <td>000563485cbb7850b0a93c6606f89c5b961c6647d1bd48...</td>\n",
       "      <td>0567532015</td>\n",
       "      <td>1585699200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23934160</th>\n",
       "      <td>000563485cbb7850b0a93c6606f89c5b961c6647d1bd48...</td>\n",
       "      <td>0706104009</td>\n",
       "      <td>1585699200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23934161</th>\n",
       "      <td>00083cda041544b2fbb0e0d2905ad17da7cf1007526fb4...</td>\n",
       "      <td>0783504004</td>\n",
       "      <td>1585699200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>31788319</th>\n",
       "      <td>fff2282977442e327b45d8c89afde25617d00124d0f999...</td>\n",
       "      <td>0929511001</td>\n",
       "      <td>1600732800</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>31788320</th>\n",
       "      <td>fff2282977442e327b45d8c89afde25617d00124d0f999...</td>\n",
       "      <td>0891322004</td>\n",
       "      <td>1600732800</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>31788321</th>\n",
       "      <td>fff380805474b287b05cb2a7507b9a013482f7dd0bce0e...</td>\n",
       "      <td>0918325001</td>\n",
       "      <td>1600732800</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>31788322</th>\n",
       "      <td>fff4d3a8b1f3b60af93e78c30a7cb4cf75edaf2590d3e5...</td>\n",
       "      <td>0833459002</td>\n",
       "      <td>1600732800</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>31788323</th>\n",
       "      <td>fffef3b6b73545df065b521e19f64bf6fe93bfd450ab20...</td>\n",
       "      <td>0898573003</td>\n",
       "      <td>1600732800</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>7854167 rows × 3 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                                              user_id:token item_id:token  \\\n",
       "23934157  000058a12d5b43e67d225668fa1f8d618c13dc232df0ca...    0727808001   \n",
       "23934158  000058a12d5b43e67d225668fa1f8d618c13dc232df0ca...    0727808007   \n",
       "23934159  000563485cbb7850b0a93c6606f89c5b961c6647d1bd48...    0567532015   \n",
       "23934160  000563485cbb7850b0a93c6606f89c5b961c6647d1bd48...    0706104009   \n",
       "23934161  00083cda041544b2fbb0e0d2905ad17da7cf1007526fb4...    0783504004   \n",
       "...                                                     ...           ...   \n",
       "31788319  fff2282977442e327b45d8c89afde25617d00124d0f999...    0929511001   \n",
       "31788320  fff2282977442e327b45d8c89afde25617d00124d0f999...    0891322004   \n",
       "31788321  fff380805474b287b05cb2a7507b9a013482f7dd0bce0e...    0918325001   \n",
       "31788322  fff4d3a8b1f3b60af93e78c30a7cb4cf75edaf2590d3e5...    0833459002   \n",
       "31788323  fffef3b6b73545df065b521e19f64bf6fe93bfd450ab20...    0898573003   \n",
       "\n",
       "          timestamp:float  \n",
       "23934157       1585699200  \n",
       "23934158       1585699200  \n",
       "23934159       1585699200  \n",
       "23934160       1585699200  \n",
       "23934161       1585699200  \n",
       "...                   ...  \n",
       "31788319       1600732800  \n",
       "31788320       1600732800  \n",
       "31788321       1600732800  \n",
       "31788322       1600732800  \n",
       "31788323       1600732800  \n",
       "\n",
       "[7854167 rows x 3 columns]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "temp = df[df['timestamp'] > 1585620000][['customer_id', 'article_id', 'timestamp']].rename(\n",
    "    columns={'customer_id': 'user_id:token', 'article_id': 'item_id:token', 'timestamp': 'timestamp:float'})\n",
    "temp"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0f27239",
   "metadata": {
    "papermill": {
     "duration": 0.065277,
     "end_time": "2022-03-20T03:23:25.191185",
     "exception": false,
     "start_time": "2022-03-20T03:23:25.125908",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "Create data file in recbole format"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "fb54432a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:23:25.330985Z",
     "iopub.status.busy": "2022-03-20T03:23:25.330083Z",
     "iopub.status.idle": "2022-03-20T03:24:02.483165Z",
     "shell.execute_reply": "2022-03-20T03:24:02.482632Z",
     "shell.execute_reply.started": "2022-03-19T07:16:24.818521Z"
    },
    "papermill": {
     "duration": 37.226498,
     "end_time": "2022-03-20T03:24:02.483347",
     "exception": false,
     "start_time": "2022-03-20T03:23:25.256849",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "!mkdir /kaggle/working/recbox_data\n",
    "temp.to_csv('/kaggle/working/recbox_data/recbox_data.inter', index=False, sep='\\t')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "cf1cf5ea",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:24:02.732875Z",
     "iopub.status.busy": "2022-03-20T03:24:02.731793Z",
     "iopub.status.idle": "2022-03-20T03:24:02.737943Z",
     "shell.execute_reply": "2022-03-20T03:24:02.738447Z",
     "shell.execute_reply.started": "2022-03-19T07:17:00.442243Z"
    },
    "papermill": {
     "duration": 0.188845,
     "end_time": "2022-03-20T03:24:02.738620",
     "exception": false,
     "start_time": "2022-03-20T03:24:02.549775",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "21"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import gc\n",
    "del temp\n",
    "gc.collect()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "2f9f96fd",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:24:02.880709Z",
     "iopub.status.busy": "2022-03-20T03:24:02.879572Z",
     "iopub.status.idle": "2022-03-20T03:24:05.595930Z",
     "shell.execute_reply": "2022-03-20T03:24:05.596790Z",
     "shell.execute_reply.started": "2022-03-19T07:17:00.552996Z"
    },
    "papermill": {
     "duration": 2.793206,
     "end_time": "2022-03-20T03:24:05.597057",
     "exception": false,
     "start_time": "2022-03-20T03:24:02.803851",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "import logging\n",
    "from logging import getLogger\n",
    "from recbole.config import Config\n",
    "from recbole.data import create_dataset, data_preparation\n",
    "from recbole.model.sequential_recommender import GRU4Rec\n",
    "from recbole.trainer import Trainer\n",
    "from recbole.utils import init_seed, init_logger"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "03cc093c",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:24:05.843816Z",
     "iopub.status.busy": "2022-03-20T03:24:05.842712Z",
     "iopub.status.idle": "2022-03-20T03:24:06.028813Z",
     "shell.execute_reply": "2022-03-20T03:24:06.030099Z",
     "shell.execute_reply.started": "2022-03-19T07:17:02.983278Z"
    },
    "papermill": {
     "duration": 0.322194,
     "end_time": "2022-03-20T03:24:06.030375",
     "exception": false,
     "start_time": "2022-03-20T03:24:05.708181",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "parameter_dict = {\n",
    "    'data_path': '/kaggle/working',\n",
    "    'USER_ID_FIELD': 'user_id',\n",
    "    'ITEM_ID_FIELD': 'item_id',\n",
    "    'TIME_FIELD': 'timestamp',\n",
    "    'user_inter_num_interval': \"[40,inf)\",\n",
    "    'item_inter_num_interval': \"[40,inf)\",\n",
    "    'load_col': {'inter': ['user_id', 'item_id', 'timestamp']},\n",
    "    'neg_sampling': None,\n",
    "    'epochs': 2,\n",
    "    'eval_args': {\n",
    "        'split': {'RS': [9, 0, 1]},\n",
    "        'group_by': 'user',\n",
    "        'order': 'TO',\n",
    "        'mode': 'full'}\n",
    "}\n",
    "config = Config(model='GRU4Rec', dataset='recbox_data', config_dict=parameter_dict)\n",
    "\n",
    "# init random seed\n",
    "init_seed(config['seed'], config['reproducibility'])\n",
    "\n",
    "# logger initialization\n",
    "init_logger(config)\n",
    "logger = getLogger()\n",
    "# Create handlers\n",
    "c_handler = logging.StreamHandler()\n",
    "c_handler.setLevel(logging.INFO)\n",
    "logger.addHandler(c_handler)\n",
    "\n",
    "# write config info into log\n",
    "# logger.info(config)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c1127367",
   "metadata": {
    "papermill": {
     "duration": 0.072153,
     "end_time": "2022-03-20T03:24:06.208954",
     "exception": false,
     "start_time": "2022-03-20T03:24:06.136801",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "Now let start spliting train data and test data in recbole"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "e7b1cfd3",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:24:06.355371Z",
     "iopub.status.busy": "2022-03-20T03:24:06.354247Z",
     "iopub.status.idle": "2022-03-20T03:25:34.154014Z",
     "shell.execute_reply": "2022-03-20T03:25:34.135949Z",
     "shell.execute_reply.started": "2022-03-19T07:17:03.140307Z"
    },
    "papermill": {
     "duration": 87.875574,
     "end_time": "2022-03-20T03:25:34.154168",
     "exception": false,
     "start_time": "2022-03-20T03:24:06.278594",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "recbox_data\n",
      "The number of users: 15459\n",
      "Average actions of users: 59.21956268598784\n",
      "The number of items: 7330\n",
      "Average actions of items: 124.9032610178742\n",
      "The number of inters: 915416\n",
      "The sparsity of the dataset: 99.19214553975321%\n",
      "Remain Fields: ['user_id', 'item_id', 'timestamp']\n"
     ]
    }
   ],
   "source": [
    "dataset = create_dataset(config)\n",
    "logger.info(dataset)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "a317f077",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:25:34.315274Z",
     "iopub.status.busy": "2022-03-20T03:25:34.314599Z",
     "iopub.status.idle": "2022-03-20T03:25:56.109208Z",
     "shell.execute_reply": "2022-03-20T03:25:56.101020Z",
     "shell.execute_reply.started": "2022-03-19T07:18:19.704645Z"
    },
    "papermill": {
     "duration": 21.880677,
     "end_time": "2022-03-20T03:25:56.109483",
     "exception": false,
     "start_time": "2022-03-20T03:25:34.228806",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[Training]: train_batch_size = [2048] negative sampling: [None]\n",
      "[Evaluation]: eval_batch_size = [4096] eval_args: [{'split': {'RS': [9, 0, 1]}, 'group_by': 'user', 'order': 'TO', 'mode': 'full'}]\n"
     ]
    }
   ],
   "source": [
    "# dataset splitting\n",
    "train_data, valid_data, test_data = data_preparation(config, dataset)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3a74f096",
   "metadata": {
    "papermill": {
     "duration": 0.082704,
     "end_time": "2022-03-20T03:25:56.277447",
     "exception": false,
     "start_time": "2022-03-20T03:25:56.194743",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "### 2. Let extract sample rows from test data.\n",
    "\n",
    "We will check items of user `0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8ce5b08a4a1f5bc71ef`. \n",
    "\n",
    "We except that last items of this user will be used as label in test data\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "410c4c02",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:01.061517Z",
     "iopub.status.busy": "2022-03-20T03:26:01.060299Z",
     "iopub.status.idle": "2022-03-20T03:26:05.674214Z",
     "shell.execute_reply": "2022-03-20T03:26:05.673707Z",
     "shell.execute_reply.started": "2022-03-19T07:18:39.031527Z"
    },
    "papermill": {
     "duration": 9.312405,
     "end_time": "2022-03-20T03:26:05.674364",
     "exception": false,
     "start_time": "2022-03-20T03:25:56.361959",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>t_dat</th>\n",
       "      <th>customer_id</th>\n",
       "      <th>article_id</th>\n",
       "      <th>price</th>\n",
       "      <th>sales_channel_id</th>\n",
       "      <th>timestamp</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>29315229</th>\n",
       "      <td>2020-07-22</td>\n",
       "      <td>0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...</td>\n",
       "      <td>0842727001</td>\n",
       "      <td>0.027102</td>\n",
       "      <td>2</td>\n",
       "      <td>1595376000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>29315230</th>\n",
       "      <td>2020-07-22</td>\n",
       "      <td>0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...</td>\n",
       "      <td>0850241005</td>\n",
       "      <td>0.020322</td>\n",
       "      <td>2</td>\n",
       "      <td>1595376000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>29315231</th>\n",
       "      <td>2020-07-22</td>\n",
       "      <td>0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...</td>\n",
       "      <td>0871517013</td>\n",
       "      <td>0.020322</td>\n",
       "      <td>2</td>\n",
       "      <td>1595376000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>30421003</th>\n",
       "      <td>2020-08-17</td>\n",
       "      <td>0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...</td>\n",
       "      <td>0903062001</td>\n",
       "      <td>0.040881</td>\n",
       "      <td>2</td>\n",
       "      <td>1597622400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>30421004</th>\n",
       "      <td>2020-08-17</td>\n",
       "      <td>0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...</td>\n",
       "      <td>0861478003</td>\n",
       "      <td>0.024525</td>\n",
       "      <td>2</td>\n",
       "      <td>1597622400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>30421005</th>\n",
       "      <td>2020-08-17</td>\n",
       "      <td>0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...</td>\n",
       "      <td>0857778011</td>\n",
       "      <td>0.032695</td>\n",
       "      <td>2</td>\n",
       "      <td>1597622400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>30421006</th>\n",
       "      <td>2020-08-17</td>\n",
       "      <td>0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...</td>\n",
       "      <td>0698286004</td>\n",
       "      <td>0.024525</td>\n",
       "      <td>2</td>\n",
       "      <td>1597622400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>30421007</th>\n",
       "      <td>2020-08-17</td>\n",
       "      <td>0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...</td>\n",
       "      <td>0698286004</td>\n",
       "      <td>0.024525</td>\n",
       "      <td>2</td>\n",
       "      <td>1597622400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>30421008</th>\n",
       "      <td>2020-08-17</td>\n",
       "      <td>0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...</td>\n",
       "      <td>0861478002</td>\n",
       "      <td>0.016339</td>\n",
       "      <td>2</td>\n",
       "      <td>1597622400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>30421009</th>\n",
       "      <td>2020-08-17</td>\n",
       "      <td>0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...</td>\n",
       "      <td>0901955001</td>\n",
       "      <td>0.024525</td>\n",
       "      <td>2</td>\n",
       "      <td>1597622400</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              t_dat                                        customer_id  \\\n",
       "29315229 2020-07-22  0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...   \n",
       "29315230 2020-07-22  0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...   \n",
       "29315231 2020-07-22  0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...   \n",
       "30421003 2020-08-17  0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...   \n",
       "30421004 2020-08-17  0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...   \n",
       "30421005 2020-08-17  0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...   \n",
       "30421006 2020-08-17  0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...   \n",
       "30421007 2020-08-17  0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...   \n",
       "30421008 2020-08-17  0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...   \n",
       "30421009 2020-08-17  0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8...   \n",
       "\n",
       "          article_id     price  sales_channel_id   timestamp  \n",
       "29315229  0842727001  0.027102                 2  1595376000  \n",
       "29315230  0850241005  0.020322                 2  1595376000  \n",
       "29315231  0871517013  0.020322                 2  1595376000  \n",
       "30421003  0903062001  0.040881                 2  1597622400  \n",
       "30421004  0861478003  0.024525                 2  1597622400  \n",
       "30421005  0857778011  0.032695                 2  1597622400  \n",
       "30421006  0698286004  0.024525                 2  1597622400  \n",
       "30421007  0698286004  0.024525                 2  1597622400  \n",
       "30421008  0861478002  0.016339                 2  1597622400  \n",
       "30421009  0901955001  0.024525                 2  1597622400  "
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "last_item_ids = df[df.customer_id == '0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8ce5b08a4a1f5bc71ef'\n",
    "                  ].tail(10).article_id.values\n",
    "df[df.customer_id == '0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8ce5b08a4a1f5bc71ef'].tail(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "1dfa904a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:05.845512Z",
     "iopub.status.busy": "2022-03-20T03:26:05.844574Z",
     "iopub.status.idle": "2022-03-20T03:26:05.848469Z",
     "shell.execute_reply": "2022-03-20T03:26:05.848986Z",
     "shell.execute_reply.started": "2022-03-19T08:01:57.513098Z"
    },
    "papermill": {
     "duration": 0.092529,
     "end_time": "2022-03-20T03:26:05.849142",
     "exception": false,
     "start_time": "2022-03-20T03:26:05.756613",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['0842727001', '0850241005', '0871517013', '0903062001',\n",
       "       '0861478003', '0857778011', '0698286004', '0698286004',\n",
       "       '0861478002', '0901955001'], dtype=object)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "last_item_ids"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e61e4796",
   "metadata": {
    "papermill": {
     "duration": 0.081369,
     "end_time": "2022-03-20T03:26:06.014083",
     "exception": false,
     "start_time": "2022-03-20T03:26:05.932714",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "Recbole use an internal ids for identify user_id and item_id, so let convert this user_id and his items into internal ids.\n",
    "* customer_id: `0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8ce5b08a4a1f5bc71ef` -> internal user id: 2\n",
    "* last bought item_id: [..., '0698286004', '0861478002', '0901955001'] -> internal item id: [..., 3237, 4377, 4559]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "56e3d2ff",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:06.185713Z",
     "iopub.status.busy": "2022-03-20T03:26:06.184790Z",
     "iopub.status.idle": "2022-03-20T03:26:06.188503Z",
     "shell.execute_reply": "2022-03-20T03:26:06.189097Z",
     "shell.execute_reply.started": "2022-03-19T07:56:12.42476Z"
    },
    "papermill": {
     "duration": 0.093653,
     "end_time": "2022-03-20T03:26:06.189274",
     "exception": false,
     "start_time": "2022-03-20T03:26:06.095621",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_data.dataset.token2id(test_data.dataset.uid_field, \n",
    "                           '0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8ce5b08a4a1f5bc71ef')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "5cb25ea8",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:06.365496Z",
     "iopub.status.busy": "2022-03-20T03:26:06.364116Z",
     "iopub.status.idle": "2022-03-20T03:26:06.370226Z",
     "shell.execute_reply": "2022-03-20T03:26:06.371133Z",
     "shell.execute_reply.started": "2022-03-19T08:02:33.042716Z"
    },
    "papermill": {
     "duration": 0.097778,
     "end_time": "2022-03-20T03:26:06.371428",
     "exception": false,
     "start_time": "2022-03-20T03:26:06.273650",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 797 4975 6339 6070 4054 6745 3237 3237 4377 4559]\n"
     ]
    }
   ],
   "source": [
    "print(dataset.token2id(dataset.iid_field, last_item_ids))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dfa2bf97",
   "metadata": {
    "papermill": {
     "duration": 0.0822,
     "end_time": "2022-03-20T03:26:06.539988",
     "exception": false,
     "start_time": "2022-03-20T03:26:06.457788",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "**Now let extract input features and labels in our test data.\n",
    "My extracted code is copy from [this source](https://recbole.io/docs/_modules/recbole/utils/case_study.html#full_sort_scores)**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "6585fd12",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:06.714700Z",
     "iopub.status.busy": "2022-03-20T03:26:06.714009Z",
     "iopub.status.idle": "2022-03-20T03:26:06.729048Z",
     "shell.execute_reply": "2022-03-20T03:26:06.729986Z",
     "shell.execute_reply.started": "2022-03-19T07:18:48.212806Z"
    },
    "papermill": {
     "duration": 0.105247,
     "end_time": "2022-03-20T03:26:06.730346",
     "exception": false,
     "start_time": "2022-03-20T03:26:06.625099",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "The batch_size of interaction: 5\n",
       "    user_id, torch.Size([5]), cpu, torch.int64\n",
       "    item_id, torch.Size([5]), cpu, torch.int64\n",
       "    timestamp, torch.Size([5]), cpu, torch.float32\n",
       "    item_length, torch.Size([5]), cpu, torch.int64\n",
       "    item_id_list, torch.Size([5, 50]), cpu, torch.int64\n",
       "    timestamp_list, torch.Size([5, 50]), cpu, torch.float32\n"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "input_features = test_data.dataset[np.isin(test_data.dataset[test_data.dataset.uid_field].numpy(), [2])]\n",
    "input_features"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "352b35aa",
   "metadata": {
    "papermill": {
     "duration": 0.099346,
     "end_time": "2022-03-20T03:26:06.936217",
     "exception": false,
     "start_time": "2022-03-20T03:26:06.836871",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "* **item_id in above interaction is used as label item**\n",
    "* **item_id_list in above interaction is used as feature items**\n",
    "\n",
    "Let check it"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "c45ec082",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:07.113806Z",
     "iopub.status.busy": "2022-03-20T03:26:07.113012Z",
     "iopub.status.idle": "2022-03-20T03:26:07.130415Z",
     "shell.execute_reply": "2022-03-20T03:26:07.129743Z",
     "shell.execute_reply.started": "2022-03-19T08:09:07.459035Z"
    },
    "papermill": {
     "duration": 0.109152,
     "end_time": "2022-03-20T03:26:07.130579",
     "exception": false,
     "start_time": "2022-03-20T03:26:07.021427",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "test label: tensor([6745, 3237, 3237, 4377, 4559])\n",
      "last 10 items from origin dataset: [ 797 4975 6339 6070 4054 6745 3237 3237 4377 4559]\n"
     ]
    }
   ],
   "source": [
    "print(\"test label: \" + str(input_features['item_id']))\n",
    "print(\"last 10 items from origin dataset: \" + str(dataset.token2id(dataset.iid_field, last_item_ids)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c9749297",
   "metadata": {
    "papermill": {
     "duration": 0.088159,
     "end_time": "2022-03-20T03:26:07.305671",
     "exception": false,
     "start_time": "2022-03-20T03:26:07.217512",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "As we expected, in last 10 items, 5 last items are used as label item. So for evaluating this user, we will have 5 sample rows in test data: \n",
    "* Input feature: ? -> Output: 6745\n",
    "* Input feature: ? -> Output: 3237\n",
    "* Input feature: ? -> Output: 3237\n",
    "* Input feature: ? -> Output: 4377\n",
    "* Input feature: ? -> Output: 4559\n",
    "\n",
    "Now, let check input features in **item_id_list**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "ae0203bf",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:07.490909Z",
     "iopub.status.busy": "2022-03-20T03:26:07.489858Z",
     "iopub.status.idle": "2022-03-20T03:26:07.497771Z",
     "shell.execute_reply": "2022-03-20T03:26:07.497176Z",
     "shell.execute_reply.started": "2022-03-19T07:18:48.243504Z"
    },
    "papermill": {
     "duration": 0.102151,
     "end_time": "2022-03-20T03:26:07.497928",
     "exception": false,
     "start_time": "2022-03-20T03:26:07.395777",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[   5,    6,    7,    8,    9,   10, 3566, 2149, 3123, 2739, 3548, 3545,\n",
       "         3807, 4115,  949, 4476, 4398, 4109, 4449, 4449, 4024, 4570,  377, 5336,\n",
       "         3491, 5340, 3608, 3608, 5138, 5138, 1880, 5234, 2442, 6000, 6000,  917,\n",
       "         6092, 5555, 5555, 6257, 3216,  797, 4975, 6339, 6070, 4054,    0,    0,\n",
       "            0,    0],\n",
       "        [   5,    6,    7,    8,    9,   10, 3566, 2149, 3123, 2739, 3548, 3545,\n",
       "         3807, 4115,  949, 4476, 4398, 4109, 4449, 4449, 4024, 4570,  377, 5336,\n",
       "         3491, 5340, 3608, 3608, 5138, 5138, 1880, 5234, 2442, 6000, 6000,  917,\n",
       "         6092, 5555, 5555, 6257, 3216,  797, 4975, 6339, 6070, 4054, 6745,    0,\n",
       "            0,    0],\n",
       "        [   5,    6,    7,    8,    9,   10, 3566, 2149, 3123, 2739, 3548, 3545,\n",
       "         3807, 4115,  949, 4476, 4398, 4109, 4449, 4449, 4024, 4570,  377, 5336,\n",
       "         3491, 5340, 3608, 3608, 5138, 5138, 1880, 5234, 2442, 6000, 6000,  917,\n",
       "         6092, 5555, 5555, 6257, 3216,  797, 4975, 6339, 6070, 4054, 6745, 3237,\n",
       "            0,    0],\n",
       "        [   5,    6,    7,    8,    9,   10, 3566, 2149, 3123, 2739, 3548, 3545,\n",
       "         3807, 4115,  949, 4476, 4398, 4109, 4449, 4449, 4024, 4570,  377, 5336,\n",
       "         3491, 5340, 3608, 3608, 5138, 5138, 1880, 5234, 2442, 6000, 6000,  917,\n",
       "         6092, 5555, 5555, 6257, 3216,  797, 4975, 6339, 6070, 4054, 6745, 3237,\n",
       "         3237,    0],\n",
       "        [   5,    6,    7,    8,    9,   10, 3566, 2149, 3123, 2739, 3548, 3545,\n",
       "         3807, 4115,  949, 4476, 4398, 4109, 4449, 4449, 4024, 4570,  377, 5336,\n",
       "         3491, 5340, 3608, 3608, 5138, 5138, 1880, 5234, 2442, 6000, 6000,  917,\n",
       "         6092, 5555, 5555, 6257, 3216,  797, 4975, 6339, 6070, 4054, 6745, 3237,\n",
       "         3237, 4377]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "input_features['item_id_list']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3a4ebb13",
   "metadata": {
    "papermill": {
     "duration": 0.087953,
     "end_time": "2022-03-20T03:26:07.675590",
     "exception": false,
     "start_time": "2022-03-20T03:26:07.587637",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "We can see:\n",
    "* For 1st row, it uses all items in training as input features.\n",
    "* For 2nd row, it uses all items in training + first label as input features\n",
    "* For 3rd row, it uses all items in training + first label + second label as input features\n",
    "* ...\n",
    "* For last row, it uses all items except last item as input features.\n",
    "\n",
    "In my previous notebooks([here](https://www.kaggle.com/code/astrung/lstm-sequential-modelwith-item-features-tutorial) and [here](https://www.kaggle.com/code/astrung/recbole-lstm-sequential-for-recomendation-tutorial/notebook)), **I use last row result for recommendation, so we are missing information from last item. **\n",
    "\n",
    "So now let fix it- find a new way for using all items"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0da61c25",
   "metadata": {
    "papermill": {
     "duration": 0.089862,
     "end_time": "2022-03-20T03:26:07.852504",
     "exception": false,
     "start_time": "2022-03-20T03:26:07.762642",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "# 2. Custom code for using all items in recommendation"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "642300a0",
   "metadata": {
    "papermill": {
     "duration": 0.08523,
     "end_time": "2022-03-20T03:26:08.025711",
     "exception": false,
     "start_time": "2022-03-20T03:26:07.940481",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "We have seen that last row is missing only last item, so fixxing ideal is simple now:\n",
    "* copy last row, add last item into it as a new interation(a row in test dataset)\n",
    "* make prediction with new interation\n",
    "\n",
    "So now let train a dummy model for testing it\n",
    "\n",
    "### 1. Make dummy model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "8e561976",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:08.204596Z",
     "iopub.status.busy": "2022-03-20T03:26:08.200688Z",
     "iopub.status.idle": "2022-03-20T03:26:42.476125Z",
     "shell.execute_reply": "2022-03-20T03:26:42.467937Z",
     "shell.execute_reply.started": "2022-03-19T07:18:48.254738Z"
    },
    "papermill": {
     "duration": 34.364819,
     "end_time": "2022-03-20T03:26:42.476364",
     "exception": false,
     "start_time": "2022-03-20T03:26:08.111545",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "GRU4Rec(\n",
      "  (item_embedding): Embedding(7330, 64, padding_idx=0)\n",
      "  (emb_dropout): Dropout(p=0.3, inplace=False)\n",
      "  (gru_layers): GRU(64, 128, bias=False, batch_first=True)\n",
      "  (dense): Linear(in_features=128, out_features=64, bias=True)\n",
      "  (loss_fct): CrossEntropyLoss()\n",
      ")\n",
      "Trainable parameters: 551104\n",
      "epoch 0 training [time: 14.43s, train loss: 3384.6924]\n",
      "Saving current: saved/GRU4Rec-Mar-20-2022_03-26-16.pth\n",
      "epoch 1 training [time: 10.94s, train loss: 3260.1609]\n",
      "Saving current: saved/GRU4Rec-Mar-20-2022_03-26-16.pth\n"
     ]
    }
   ],
   "source": [
    "# model loading and initialization\n",
    "model = GRU4Rec(config, train_data.dataset).to(config['device'])\n",
    "logger.info(model)\n",
    "\n",
    "# trainer loading and initialization\n",
    "trainer = Trainer(config, model)\n",
    "\n",
    "# model training\n",
    "best_valid_score, best_valid_result = trainer.fit(train_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "330ca134",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:42.672002Z",
     "iopub.status.busy": "2022-03-20T03:26:42.671191Z",
     "iopub.status.idle": "2022-03-20T03:26:42.674858Z",
     "shell.execute_reply": "2022-03-20T03:26:42.675478Z",
     "shell.execute_reply.started": "2022-03-19T07:19:18.347113Z"
    },
    "papermill": {
     "duration": 0.104305,
     "end_time": "2022-03-20T03:26:42.675633",
     "exception": false,
     "start_time": "2022-03-20T03:26:42.571328",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "GRU4Rec(\n",
       "  (item_embedding): Embedding(7330, 64, padding_idx=0)\n",
       "  (emb_dropout): Dropout(p=0.3, inplace=False)\n",
       "  (gru_layers): GRU(64, 128, bias=False, batch_first=True)\n",
       "  (dense): Linear(in_features=128, out_features=64, bias=True)\n",
       "  (loss_fct): CrossEntropyLoss()\n",
       ")"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.eval()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "02773d9a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:42.870629Z",
     "iopub.status.busy": "2022-03-20T03:26:42.869792Z",
     "iopub.status.idle": "2022-03-20T03:26:42.873287Z",
     "shell.execute_reply": "2022-03-20T03:26:42.873790Z",
     "shell.execute_reply.started": "2022-03-19T07:19:18.355205Z"
    },
    "papermill": {
     "duration": 0.105847,
     "end_time": "2022-03-20T03:26:42.873956",
     "exception": false,
     "start_time": "2022-03-20T03:26:42.768109",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([5, 50])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "input_features['item_id_list'].shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f22ab4c5",
   "metadata": {
    "papermill": {
     "duration": 0.094002,
     "end_time": "2022-03-20T03:26:43.063520",
     "exception": false,
     "start_time": "2022-03-20T03:26:42.969518",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "Our sequence items is always have fix length(50). So if we have more than 50 items, we need to drop earlier items, and if there are less than 50 items, we need to add a padding(0) into input item features. As example:\n",
    "* If last row input = [3, 4, 7,..., 20, 0, 0 ,0] (47 items < 50 item, so we have padding), after adding id=30, we will have input = [3, 4, 7,..., 20, 30, 0 ,0] Now our sequence lenght = 48 items.\n",
    "* If last row input = [3, 4, 7,..., 20, 9, 10 ,12] (50 items), after adding id=30, we will have input = [4, 7,..., 9, 10, 12, 30] (drop first item and add last item).Now our sequence lenght still = 50 items.\n",
    "\n",
    "Now let implement it.\n",
    "\n",
    "First let extract last row from all interation when internal_user_id = 2 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "102bafb5",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:43.258540Z",
     "iopub.status.busy": "2022-03-20T03:26:43.257542Z",
     "iopub.status.idle": "2022-03-20T03:26:43.281126Z",
     "shell.execute_reply": "2022-03-20T03:26:43.280610Z",
     "shell.execute_reply.started": "2022-03-19T08:34:57.763854Z"
    },
    "papermill": {
     "duration": 0.122703,
     "end_time": "2022-03-20T03:26:43.281269",
     "exception": false,
     "start_time": "2022-03-20T03:26:43.158566",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "The batch_size of interaction: 50\n",
       "    user_id, torch.Size([50]), cpu, torch.int64\n",
       "    item_id, torch.Size([50]), cpu, torch.int64\n",
       "    timestamp, torch.Size([50]), cpu, torch.float32\n",
       "    item_length, torch.Size([50]), cpu, torch.int64\n",
       "    item_id_list, torch.Size([50, 50]), cpu, torch.int64\n",
       "    timestamp_list, torch.Size([50, 50]), cpu, torch.float32\n"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "index = np.isin(dataset[dataset.uid_field].numpy(), [2])\n",
    "input_interaction = dataset[index]\n",
    "input_interaction"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0349a339",
   "metadata": {
    "papermill": {
     "duration": 0.096329,
     "end_time": "2022-03-20T03:26:43.472695",
     "exception": false,
     "start_time": "2022-03-20T03:26:43.376366",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "Now let add last item into sequences, and make new interaction.\n",
    "We also need to edit sequence lenght (without padding)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "76330a66",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:43.675855Z",
     "iopub.status.busy": "2022-03-20T03:26:43.674868Z",
     "iopub.status.idle": "2022-03-20T03:26:43.683634Z",
     "shell.execute_reply": "2022-03-20T03:26:43.684193Z",
     "shell.execute_reply.started": "2022-03-19T08:39:53.562108Z"
    },
    "papermill": {
     "duration": 0.115591,
     "end_time": "2022-03-20T03:26:43.684381",
     "exception": false,
     "start_time": "2022-03-20T03:26:43.568790",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "The batch_size of interaction: 1\n",
       "    item_id_list, torch.Size([1, 50]), cpu, torch.int64\n",
       "    item_length, torch.Size([1]), cpu, torch.int64\n"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "from recbole.data.interaction import Interaction\n",
    "\n",
    "def add_last_item(old_interaction, last_item_id, max_len=50):\n",
    "    new_seq_items = old_interaction['item_id_list'][-1]\n",
    "    if old_interaction['item_length'][-1].item() < max_len:\n",
    "        new_seq_items[input_interaction['item_length'][-1].item()] = last_item_id\n",
    "    else:\n",
    "        new_seq_items = torch.roll(new_seq_items, -1)\n",
    "        new_seq_items[-1] = last_item_id\n",
    "    return new_seq_items.view(1, len(new_seq_items))\n",
    "\n",
    "test = {\n",
    "            'item_id_list': add_last_item(input_interaction, input_interaction['item_id'][-1].item(), model.max_seq_length),\n",
    "            'item_length': torch.tensor(\n",
    "                [input_interaction['item_length'][-1].item() + 1\n",
    "                 if input_interaction['item_length'][-1].item() < model.max_seq_length else model.max_seq_length])\n",
    "        }\n",
    "new_inter = Interaction(test)\n",
    "new_inter"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "61a9aaa8",
   "metadata": {
    "papermill": {
     "duration": 0.097313,
     "end_time": "2022-03-20T03:26:43.878524",
     "exception": false,
     "start_time": "2022-03-20T03:26:43.781211",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "Interaction for GRU4Rec model need to have only `item_id_list` and `item_lenght`. You can drop other key.\n",
    "If you want more information, you can check [GRU4Rec code](https://recbole.io/docs/_modules/recbole/model/sequential_recommender/gru4rec.html#GRU4Rec)\n",
    "\n",
    "Then we can apply the remaining prediction code from [full_sort_scores](https://recbole.io/docs/_modules/recbole/utils/case_study.html#full_sort_scores)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "7da9030b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:44.084630Z",
     "iopub.status.busy": "2022-03-20T03:26:44.083600Z",
     "iopub.status.idle": "2022-03-20T03:26:44.106014Z",
     "shell.execute_reply": "2022-03-20T03:26:44.106586Z",
     "shell.execute_reply.started": "2022-03-19T08:46:00.688378Z"
    },
    "papermill": {
     "duration": 0.129901,
     "end_time": "2022-03-20T03:26:44.106769",
     "exception": false,
     "start_time": "2022-03-20T03:26:43.976868",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "new_inter = new_inter.to(config['device'])\n",
    "new_scores = model.full_sort_predict(new_inter)\n",
    "new_scores = new_scores.view(-1, test_data.dataset.item_num)\n",
    "new_scores[:, 0] = -np.inf  # set scores of [pad] to -inf"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d7071fb",
   "metadata": {
    "papermill": {
     "duration": 0.097247,
     "end_time": "2022-03-20T03:26:44.301335",
     "exception": false,
     "start_time": "2022-03-20T03:26:44.204088",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "So now by combining all fragments,we have a new function for predicting with all item in dataset. You can use this custom code for all sequential model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "28361728",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:44.517838Z",
     "iopub.status.busy": "2022-03-20T03:26:44.516679Z",
     "iopub.status.idle": "2022-03-20T03:26:44.519542Z",
     "shell.execute_reply": "2022-03-20T03:26:44.520033Z",
     "shell.execute_reply.started": "2022-03-19T08:50:43.786113Z"
    },
    "papermill": {
     "duration": 0.113123,
     "end_time": "2022-03-20T03:26:44.520196",
     "exception": false,
     "start_time": "2022-03-20T03:26:44.407073",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "import torch\n",
    "from recbole.data.interaction import Interaction\n",
    "\n",
    "def add_last_item(old_interaction, last_item_id, max_len=50):\n",
    "    new_seq_items = old_interaction['item_id_list'][-1]\n",
    "    if old_interaction['item_length'][-1].item() < max_len:\n",
    "        new_seq_items[old_interaction['item_length'][-1].item()] = last_item_id\n",
    "    else:\n",
    "        new_seq_items = torch.roll(new_seq_items, -1)\n",
    "        new_seq_items[-1] = last_item_id\n",
    "    return new_seq_items.view(1, len(new_seq_items))\n",
    "\n",
    "def predict_for_all_item(external_user_id, dataset, model):\n",
    "    model.eval()\n",
    "    with torch.no_grad():\n",
    "        uid_series = dataset.token2id(dataset.uid_field, [external_user_id])\n",
    "        index = np.isin(dataset[dataset.uid_field].numpy(), uid_series)\n",
    "        input_interaction = dataset[index]\n",
    "        test = {\n",
    "            'item_id_list': add_last_item(input_interaction, \n",
    "                                          input_interaction['item_id'][-1].item(), model.max_seq_length),\n",
    "            'item_length': torch.tensor(\n",
    "                [input_interaction['item_length'][-1].item() + 1\n",
    "                 if input_interaction['item_length'][-1].item() < model.max_seq_length else model.max_seq_length])\n",
    "        }\n",
    "        new_inter = Interaction(test)\n",
    "        new_inter = new_inter.to(config['device'])\n",
    "        new_scores = model.full_sort_predict(new_inter)\n",
    "        new_scores = new_scores.view(-1, test_data.dataset.item_num)\n",
    "        new_scores[:, 0] = -np.inf  # set scores of [pad] to -inf\n",
    "    return torch.topk(new_scores, 10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "07580e6e",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-03-20T03:26:44.719887Z",
     "iopub.status.busy": "2022-03-20T03:26:44.718743Z",
     "iopub.status.idle": "2022-03-20T03:26:44.789126Z",
     "shell.execute_reply": "2022-03-20T03:26:44.789832Z",
     "shell.execute_reply.started": "2022-03-19T08:49:01.592811Z"
    },
    "papermill": {
     "duration": 0.173425,
     "end_time": "2022-03-20T03:26:44.790032",
     "exception": false,
     "start_time": "2022-03-20T03:26:44.616607",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.return_types.topk(\n",
       "values=tensor([[5.4805, 5.2197, 5.1685, 5.1523, 5.0042, 4.9986, 4.9978, 4.9962, 4.9898,\n",
       "         4.9557]], device='cuda:0'),\n",
       "indices=tensor([[5412,  782, 2668, 1608, 4579, 2426,  294, 2427, 5835, 2669]],\n",
       "       device='cuda:0'))"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "predict_for_all_item('0109ad0b5a76924a1b58be677409bb601cc8bead9a87b8ce5b08a4a1f5bc71ef', \n",
    "                     dataset, model) # we feed directly origin dataset, not train data or test data"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c7564dc",
   "metadata": {
    "papermill": {
     "duration": 0.098422,
     "end_time": "2022-03-20T03:26:44.992841",
     "exception": false,
     "start_time": "2022-03-20T03:26:44.894419",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "Congratulation !!!.Now you can use all data as train set, don't need for a test set, but still can predict directly from dataset without testset.Now let apply it into our previous notebook.\n",
    "\n",
    "I have create new notebooks for applying our customize function for using all items as input for recommendation:\n",
    "* Using only interactions: https://www.kaggle.com/astrung/sequential-model-fixed-missing-last-item\n",
    "* Using interactions with item features: https://www.kaggle.com/code/astrung/lstm-model-with-item-infor-fix-missing-last-item\n",
    "\n",
    "Please check and upvote it"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "efefe8dc",
   "metadata": {
    "papermill": {
     "duration": 0.098691,
     "end_time": "2022-03-20T03:26:45.190857",
     "exception": false,
     "start_time": "2022-03-20T03:26:45.092166",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.12"
  },
  "papermill": {
   "default_parameters": {},
   "duration": 309.140629,
   "end_time": "2022-03-20T03:26:48.101763",
   "environment_variables": {},
   "exception": null,
   "input_path": "__notebook__.ipynb",
   "output_path": "__notebook__.ipynb",
   "parameters": {},
   "start_time": "2022-03-20T03:21:38.961134",
   "version": "2.3.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
